import html
import re
from typing import List

from langchain_core.messages import BaseMessage
from langchain_core.utils import print_text


def unescape_html(val: str) -> str:
    if not val:
        return val
    try:
        return html.unescape(val)
    except Exception as e:
        return val

def replace_file_search_fix(val: str) -> str:
    if not val:
        return val
    try:
        result = re.sub(r'^<<<<<<<\s*SEARCH.*$', '<<<<<<< SEARCH', val, flags=re.MULTILINE)
        return result
    except Exception as e:
        print('replace_file_search_fix error', e)
        return val

def print_message(messages):
    for msg in messages:
        if hasattr(msg, 'type') and hasattr(msg, 'content'):
            print_text(text=f"<<{msg.type}>>\n", color="red")
            content = msg.content
        elif isinstance(msg, dict):
            role = msg.get("role", "unknown")
            print_text(text=f"<<{role}>>\n", color="red")
            content = msg.get("content", "")
        else:
            print_text(text=f"<<unknown>>\n", color="red")
            content = str(msg)

        if isinstance(content, str):
            content_text = content
        elif isinstance(content, list):
            text_parts = []
            for item in content:
                if isinstance(item, dict):
                    if item.get("type") == "text" and "text" in item:
                        text_parts.append(item["text"])
                    elif isinstance(item.get("text"), str):
                        text_parts.append(item["text"])
                    elif item.get("type") == "image_url":
                        text_parts.append("[IMAGE]")
                elif isinstance(item, str):
                    text_parts.append(item)
            content_text = "\n".join(text_parts)
        else:
            content_text = str(content) if content else ""

        print_text(text=f"{content_text}\n", color="green")

def dict_to_json_str(d: dict) -> str:
    items = []
    for k, v in d.items():
        if isinstance(v, str):
            items.append(f'"{k}": "{v}"')
        elif v is None:
            items.append(f'"{k}": null')
        elif isinstance(v, bool):
            items.append(f'"{k}": {str(v).lower()}')
        else:
            items.append(f'"{k}": {v}')
    return '{' + ', '.join(items) + '}'

def get_message_content(content) -> str:
    """
    获取消息的文本内容，处理不同类型的content格式

    Args:
        content: 可以是 BaseMessage, str, list 或其他类型

    Returns:
        提取出的文本内容字符串
    """
    # 如果是 BaseMessage 类型，递归处理其 content 属性
    if isinstance(content, BaseMessage):
        return get_message_content(content.content)

    # 如果是字符串，直接返回
    if isinstance(content, str):
        return content

    # 如果是列表，提取所有文本部分
    if isinstance(content, list):
        text_parts = []
        for item in content:
            if isinstance(item, dict):
                if item.get("type") == "text" and "text" in item:
                    text_parts.append(item["text"])
                elif isinstance(item.get("text"), str):
                    text_parts.append(item["text"])
            elif isinstance(item, str):
                text_parts.append(item)
        return "\n".join(text_parts)

    # 其他类型转换为字符串
    return str(content) if content else ""


def set_message_content(content, new_content: str):
    """
    设置消息的内容，保持原有的content格式

    Args:
        content: 原始 content，可以是 BaseMessage, str, list 或其他类型
        new_content: 要设置的新内容字符串

    Returns:
        更新后的 content
    """
    if isinstance(content, BaseMessage):
        content.content = set_message_content(content.content, new_content)
        return content

    if isinstance(content, str):
        return new_content

    if isinstance(content, list):
        content_copy = content.copy() if isinstance(content, list) else content
        updated = False
        for item in content_copy:
            if isinstance(item, dict):
                if item.get("type") == "text" and "text" in item:
                    item["text"] = new_content
                    updated = True
                    break
                elif isinstance(item.get("text"), str):
                    item["text"] = new_content
                    updated = True
                    break

        if not updated:
            content_copy.insert(0, {"type": "text", "text": new_content})

        return content_copy
    return new_content

def render(template: str, **kwargs) -> str:
    """
    Replace {{param}} placeholders in template with values from kwargs.

    Args:
        template: Template string containing {{param}} placeholders
        **kwargs: Parameters to substitute in the template

    Returns:
        Rendered template string with placeholders replaced
    """
    if not template:
        return template

    try:
        result = template
        for key, value in kwargs.items():
            placeholder = f"{{{{{key}}}}}"
            result = result.replace(placeholder, str(value))
        return result
    except Exception as e:
        print(f'render error: {e}')
        return template
